/*!
 * @file        apm32_sdrc.c
 *
 * @brief       This file contains all the functions for the SDRAM controler peripheral      
 *
 * @version     V1.0.0
 *
 * @date        2020-2-25
 *
 */
#include "apm32f10x_sdrc.h"

/** @addtogroup Peripherals_Library Standard Peripheral Library  
  @{
*/

/** @addtogroup SDRC_Driver  SDRC Driver
  @{
*/

/** @addtogroup  SDRC_Fuctions Fuctions
  @{
*/

/*!
 * @brief       SDRAM controler configuration
 *
 * @param       config:     Pointer to a SDRC_Config_T structure that 
 *                          contains the configuration information for the SDRC peripheral
 *
 * @retval      None
 *
 * @note       
 */
void SDRC_Config(SDRC_Config_T * config)
{
    SDRC->SW_B.EN = 1;
    while(!SDRC->CTRL0_B.INIT);

    SDRC->CFG_B.BAW = config->bankBitsNum;
    SDRC->CFG_B.RAW = config->rowBitsNum;
    SDRC->CFG_B.CAW = config->colBitsNum;

    SDRC->MASK_B.MEMSIZE = config->size;
    SDRC->CTRL1_B.CLKPHA = config->clkPhase;

    SDRC_ConfigTiming(&config->timing);

    SDRC->CTRL0_B.MODESET = 1;
    while(!SDRC->CTRL0_B.MODESET);
    
    SDRC->CTRL1_B.RDEN = 1;
    SDRC->CTRL1_B.RDDLAY = 7;
    //SDRC->CTRL1_B.WPEN = 1;
}

/*!
 * @brief       Fills each config member with its default value
 *
 * @param       config:     Pointer to a SDRC_Config_T structure which will be initialized
 *
 * @retval      None
 *
 * @note       
 */
void SDRC_ConfigStructInit(SDRC_Config_T * config)
{
    config->bankBitsNum = 1;
    config->clkPhase = SDRC_CLK_PHASE_REVERSE;//SDRC_CLK_PHASE_REVERSE;
    config->colBitsNum = 8;
    config->rowBitsNum = 12;
    config->size = SDRC_SIZE_8MB;
    
    SDRC_TimingStructInit(&config->timing);
}

/*!
 * @brief       Timing configuration 
 *
 * @param       timingConfig:   Pointer to a SDRC_TimingConfig_T structure that
 *                              contains the configuration information SDRC Timing
 *
 * @retval      None
 *
 * @note       
 */
void SDRC_ConfigTiming(SDRC_TimingConfig_T * timingConfig)
{
    SDRC->TIMI0_B.RAS = timingConfig->tRAS;
    SDRC->TIMI0_B.RCD = timingConfig->tRCD;
    SDRC->TIMI0_B.RP = timingConfig->tRP;
    SDRC->TIMI0_B.WR = timingConfig->tWR;
    SDRC->TIMI0_B.ARP = timingConfig->tARP;
    SDRC->TIMI0_B.RC = timingConfig->tRC;
    
    SDRC->TIMI0_B.CASLAT0 = timingConfig->latencyCAS & 0x02;
    SDRC->TIMI0_B.CASLAT1 = (timingConfig->latencyCAS >> 2) & 0x01;

    SDRC->TIMI0_B.XSR0 = timingConfig->tXSR & 0X0F;
    SDRC->TIMI0_B.XSR1 = (timingConfig->tXSR >> 4) & 0X1F;  

    SDRC->REF_B.REFPR = timingConfig->tRFP;
}

/*!
 * @brief       Fills each config member with its default value
 *
 * @param       config:     Pointer to a SDRC_TimingConfig_T structure which will be initialized
 *
 * @retval      None
 *
 * @note       
 */
void SDRC_TimingStructInit(SDRC_TimingConfig_T * timingConfig)
{
    timingConfig->latencyCAS = SDRC_CAS_LATENCY_3;
    timingConfig->tARP = 9;
    timingConfig->tRAS = 4;
    timingConfig->tRC = 6;
    timingConfig->tRCD = 1;
    timingConfig->tRP = 1;
    timingConfig->tWR = 1;
    timingConfig->tXSR = 6;
    timingConfig->tRFP = 0XC3;
}

/*!
 * @brief       Set number of bank bits
 *
 * @param       bankWidth:  Specifies the bank bits number
 *
 * @retval      None
 *
 * @note       
 */
void SDRC_ConfigBankWidth(uint8_t bankWidth)
{
    SDRC->CFG_B.BAW = bankWidth;
}

/*!
 * @brief       Set address bus width
 *
 * @param       rowAddrWidth:   Specifies the row address bits number
 *
 * @param       colAddrWidth:   Specifies the column address bits number
 *
 * @retval      None
 *
 * @note       
 */
void SDRC_ConfigAddrBusWidth(uint8_t rowAddrWidth, uint8_t colAddrWidth)
{
    SDRC->CFG_B.RAW = rowAddrWidth;
    SDRC->CFG_B.CAW = colAddrWidth;
}

/*!
 * @brief       Set stable time after power up
 *
 * @param       stableTime: Numper of the clock 
 *
 * @retval      None
 *
 * @note       
 */
void SDRC_ConfigStableTimePowerup(uint16_t stableTime)
{
    SDRC->TIMI1_B.STBTIME = stableTime;
}

/*!
 * @brief       Number of auto-refreshes during initialization
 *
 * @param       num:    Number of auto-refreshes
 *
 * @retval      None
 *
 * @note       
 */
void SDRC_ConfigAutoRefreshNumDuringInit(uint8_t num)
{
    SDRC->TIMI1_B.ARNUM = num;
}

/*!
 * @brief       Number of SDRAM internal banks to be open at any time;
 *
 * @param       banks:  Number of banks
 *
 * @retval      None
 *
 * @note       
 */
void SDRC_ConfigOpenBank(uint8_t banks)
{
    SDRC->CTRL0_B.BANKOPEN = banks;
}

/*!
 * @brief       Read self-refresh status
 *
 * @param       None
 *
 * @retval      The status of self-refresh (SET or RESET)
 *
 * @note       
 */
uint8_t SDRC_ReadSelfRefreshStatus(void)
{
    uint8_t ret;

    ret = SDRC->CTRL0_B.SRMF ? SET : RESET;

    return ret;
}

/*!
 * @brief       Set mode register
 *
 * @param       None
 *
 * @retval      None
 *
 * @note       
 */
void SDRC_EnableModeRegisterSet(void)
{
    SDRC->CTRL0_B.MODESET = 1;
}

/*!
 * @brief       Enter power down mode
 *
 * @param       None
 *
 * @retval      None
 *
 * @note       
 */
void SDRC_EnterPowerdownMode(void)
{
    SDRC->CTRL0_B.PDM = 1;
}

/*!
 * @brief       Exit self-refresh mode
 *
 * @param       None
 *
 * @retval      None
 *
 * @note       
 */
void SDRC_EixtSlefRefreshMode(void)
{
    SDRC->CTRL0_B.SELREF = 0;
}

/*!
 * @brief       Enter self-refresh mode
 *
 * @param       None
 *
 * @retval      None
 *
 * @note       
 */
void SDRC_EnterSlefRefreshMode(void)
{
    SDRC->CTRL0_B.SELREF = 1;
}

/*!
 * @brief       Init SDRAM
 *
 * @param       None
 *
 * @retval      None
 *
 * @note       
 */
void SDRC_EnableInit(void)
{
    SDRC->CTRL0_B.INIT = 1;
}

/*!
 * @brief       Set fresh type before enter self-refresh
 *
 * @param       fr:     Specifies the type
 *
 * @retval      None
 *
 * @note       
 */
void SDRC_ConfigFullRefreshBeforeSR(SDRC_FR_T fr)
{
    SDRC->CTRL0_B.FRBSR = fr;
}

/*!
 * @brief       Set fresh type after exit self-refresh
 *
 * @param       fr:     Specifies the type
 *
 * @retval      None
 *
 * @note       
 */
void SDRC_ConfigFullRefreshEnterSR(SDRC_FR_T fr)
{
    SDRC->CTRL0_B.FRASR = fr;
}

/*!
 * @brief       Set precharge type
 *
 * @param       type:   Specifies the precharge type
 *
 * @retval      None
 *
 * @note       
 */
void SDRC_SetPrechargeType(SDRC_PC_TYPE_T type)
{
    SDRC->CTRL0_B.PCTYPE = type;
}

/*!
 * @brief       Set refresh period
 *
 * @param       period:   Specifies the refresh period.Numger of clock.
 *
 * @retval      None
 *
 * @note       
 */
void SDRC_SetRefreshPeriod(uint8_t period)
{
    SDRC->REF_B.REFPR = period;
}

/*!
 * @brief       Set memory size
 *
 * @param       size:   Specifies memory size
 *
 * @retval      None
 *
 * @note       
 */
void SDRC_SetSize(SDRC_SIZE_T size)
{
    SDRC->MASK_B.MEMSIZE = size;
}

/*!
 * @brief       Enable SDRC controler
 *
 * @param       None
 *
 * @retval      None
 *
 * @note       
 */
void SDRC_Enable(void)
{
    SDRC->SW_B.EN = 1;
}

/*!
 * @brief       Disable SDRC controler
 *
 * @param       None
 *
 * @retval      None
 *
 * @note       
 */
void SDRC_Disable(void)
{
    SDRC->SW_B.EN = 0;
}

/*!
 * @brief       Set SDRC clock phase
 *
 * @param       clkPhase:   Specifies clock phase
 *
 * @retval      None
 *
 * @note       
 */
void SDRC_SetClkPhase(SDRC_CLK_PHASE_T clkPhase)
{
    SDRC->CTRL1_B.CLKPHA = clkPhase;
}

/**@} end of group SDRC_Fuctions*/
/**@} end of group SDRC_Driver */
/**@} end of group Peripherals_Library*/

